package com.shawn.spring.boot.redis.service.impl;

import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.exact;

import com.shawn.spring.boot.redis.entity.CoffeeCacheEntity;
import com.shawn.spring.boot.redis.entity.CoffeeEntity;
import com.shawn.spring.boot.redis.repository.CoffeeCacheRepository;
import com.shawn.spring.boot.redis.repository.CoffeeRepository;
import com.shawn.spring.boot.redis.service.CoffeeCacheService;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;

/**
 * @author shawn
 * @since 2020/9/4
 */
@Slf4j
@Service
public class CoffeeCacheServiceImpl implements CoffeeCacheService {

  @Autowired private CoffeeRepository coffeeRepository;
  @Autowired private CoffeeCacheRepository cacheRepository;

  @Override
  public List<CoffeeEntity> findAllCoffee() {
    return coffeeRepository.findAll();
  }

  @Override
  public Optional<CoffeeEntity> findSimpleCoffeeFromCache(String name) {
    Optional<CoffeeCacheEntity> cached = cacheRepository.findOneByName(name);
    if (cached.isPresent()) {
      CoffeeCacheEntity coffeeCache = cached.get();
      CoffeeEntity coffee =
          CoffeeEntity.builder().name(coffeeCache.getName()).price(coffeeCache.getPrice()).build();
      log.info("Coffee {} found in cache.", coffeeCache);
      return Optional.of(coffee);
    } else {
      Optional<CoffeeEntity> raw = findOneCoffee(name);
      raw.ifPresent(
          c -> {
            CoffeeCacheEntity coffeeCache =
                CoffeeCacheEntity.builder()
                    .id(c.getId())
                    .name(c.getName())
                    .price(c.getPrice())
                    .build();
            log.info("Save Coffee {} to cache.", coffeeCache);
            cacheRepository.save(coffeeCache);
          });
      return raw;
    }
  }

  @Override
  public Optional<CoffeeEntity> findOneCoffee(String name) {
    ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", exact().ignoreCase());
    Optional<CoffeeEntity> coffee =
        coffeeRepository.findOne(Example.of(CoffeeEntity.builder().name(name).build(), matcher));
    log.info("Coffee Found: {}", coffee);
    return coffee;
  }
}
